#!/usr/bin/env python
#
# Copyright 2008 Whitley Media
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-----------------------------------------------------------------------------
# Name:		GUNK
# Author:  	Shannon Whitley
# Date:		04/16/2008
# Purpose:	Provide Soap access to Google App Engine Datastore.
# Version:	1.0
#-----------------------------------------------------------------------------
# M O D I F I C A T I O N S
#
# 1. S. Whitley		04/16/2008	Initial Release
#-----------------------------------------------------------------------------
import wsgiref.handlers
import string
import os 

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template


class GUNK(db.Model):
	Bucket = db.StringProperty()
	Name = db.StringProperty()
	Value = db.TextProperty()


class MainHandler(webapp.RequestHandler):

	
	def __init__ (self):
		#target namespace
		self.ns   = "http://www.whitleymedia.com/websvcs/"
		#server secret - client secret must match
		self.secret = "[My Secret]"
	
	def get(self):

		if self.request.environ.get('HTTPS', '') == 'on':
			protocol = 'https'
		else:
			protocol = 'http'
		#This address
		location = '%s://%s%s/'%(protocol, self.request.environ['HTTP_HOST'],
						self.request.environ.get('REQUEST_URI', ''))
		#Load WSDL
		path = os.path.join(os.path.dirname(__file__), 'GUNK.wsdl')
		templatevalues = {   'location': location, 'ns':self.ns  }

		self.response.headers['Content-Type'] = "text/xml"
		self.response.out.write(template.render(path, templatevalues))		
	
	def post(self):

		try:
			bucket=""
			name = ""
			value = ""
			soap = self.request.body
			start = string.find(soap,"<soap:Body>",0)
			end = string.find(soap,"</soap:Body>",start)
			end += 12
			body = soap[start:end]
			
			#Soap Methods [Get, Put, Del]
			method = body[12:15]
			method = method[0:3]
			
			#secret
			start = string.find(body,"<Secret>")
			start += 8
			end = string.find(body,"</Secret>",start)
			secret = body[start:end]			
			if secret != self.secret:
				raise Exception('Invalid Secret.  The Secret in the Soap client does not match the server Secret.')
			
			#bucket
			start = string.find(body,"<Bucket>")
			start += 8
			end = string.find(body,"</Bucket>",start)
			bucket = body[start:end]
			#name
			start = string.find(body,"<Name>")
			start += 6
			end = string.find(body,"</Name>",start)
			name = body[start:end]	
			#value
			start = string.find(body,"<Value>")
			start+= 7
			end = string.find(body,"</Value>",start)
			value = body[start:end]		
			
			#Xlat to longer method name.
			if method == "Del":
				method = "Delete"		

			result = "false"
			resp = ""
			
			#Method Processing
			if method == "Put":
				gunk = GUNK()
				gunk.Bucket = bucket
				gunk.Name = name
				gunk.Value = value
				db.put(gunk)
				result = "true"
			
			if method == "Get":
				results = db.GqlQuery("Select * from GUNK WHERE Bucket=:1 AND Name=:2",bucket,name)
				result = ""
				for row in results:
					result += row.to_xml()
				if len(result) > 0:
					result = "<entities>" + result + "</entities>"
				
			if method == "Delete":
				results = db.GqlQuery("Select * from GUNK WHERE Bucket=:1 AND Name=:2",bucket,name)
				for row in results:
					row.delete()
				result = "true"

			#Soap Response
			resp = '<' + method + 'Response xmlns="' + self.ns + '">\r\n'
			resp +='<' + method + 'Result><![CDATA[' + result + ']]></' + method + 'Result>\r\n'
			resp +='</' + method + 'Response>\r\n'			

		except Exception, e:
			resp = '<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r\n'
			resp += '<faultcode></faultcode>\r\n'
			resp += '  <faultstring>' + e.message + '</faultstring>\r\n'
			resp += '  <detail><m:msg xmlns:m="http://example.org/faults/exceptions">Bucket: ' + bucket + ' Name: ' + name + ' Value: ' + value + '</m:msg></detail>\r\n'
			resp += '</soap:Fault>\r\n'
		
		
		self.response.headers['Content-Type'] = "text/xml"

		#Soap Envelope
		self.response.out.write('<?xml version="1.0" encoding="utf-8"?>\r\n')
		self.response.out.write('<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r\n')
		self.response.out.write('<soap:Body>\r\n')
		self.response.out.write	(resp)
		self.response.out.write('</soap:Body>\r\n')
		self.response.out.write('</soap:Envelope>\r\n')
		

def main():
  application = webapp.WSGIApplication([('/', MainHandler)],
                                       debug=False)
  wsgiref.handlers.CGIHandler().run(application)


if __name__ == '__main__':
  main()
